﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using smsclictr.automation;
using System.Management;
using Microsoft.SystemCenter.Orchestrator.Integration;

namespace OpalisAddOn.Schedules
{
    [Activity("Get Patch Dates", Description = "Get Dates that reference Patch Tuesday", ShowFilters = false)]
    public class PatchDates : IActivity
    {
        public void Design(IActivityDesigner designer)
        {
            designer.AddInput("Year").NotRequired();
            designer.AddInput("Month").NotRequired();
            designer.AddInput("Time").NotRequired();

            designer.AddInput("Occurence").WithListBrowser(new string[] { "first", "second", "third", "fourth" }).NotRequired().WithDefaultValue("first");
            designer.AddInput("Weekday").WithEnumBrowser(typeof(DayOfWeek)).NotRequired();

            designer.AddOutput("Date_Now").AsDateTime();
            designer.AddOutput("Date_Patchday").AsDateTime().WithDescription("Shows the date of the Patch-Day in the current month");
            designer.AddOutput("Date_PatchdayNext").AsDateTime().WithDescription("Shows the date of the next Patch-Day");
            designer.AddOutput("Date_Target").AsDateTime().WithDescription("Shows the date of the target occurence in the current month");
            designer.AddOutput("Date_TargetNext").AsDateTime().WithDescription("Shows the date of the next target occurence");
            designer.AddOutput("Date_isTargetToday").AsString().WithDescription("Shows if the target date is today");
            designer.AddOutput("Date_isPast").AsString().WithDescription("Shows if date is in the past");
        }

        public void Execute(IActivityRequest request, IActivityResponse response)
        {
            response.Publish("Date_Now", DateTime.Now);


            DateTime pDay = DateTime.Now; 
            int year = DateTime.Now.Year;
            int month = DateTime.Now.Month;
            int hour = 0;
            int minute = 0;
            int second = 0;

            response.Publish("Date_isTargetToday", false);
            response.Publish("Date_isPast", false);

            if (request.Inputs.Contains("Year") & request.Inputs.Contains("Month"))
            {
                year = request.Inputs["Year"].AsInt16();
                month = request.Inputs["Month"].AsInt16();

                if (request.Inputs.Contains("Time"))
                {
                    string sTime = request.Inputs["Time"].AsString();
                    string[] sTimes = sTime.Split(':');
                    if (sTimes.Length == 2)
                    {
                        hour = int.Parse(sTimes[0]);
                        minute = int.Parse(sTimes[1]);
                    }
                    if (sTimes.Length == 3)
                    {
                        second = int.Parse(sTimes[2]);
                    }
                }

                pDay = PatchDay(year, month, hour, minute, second);    

            }
            else
            {
                if (request.Inputs.Contains("Time"))
                {
                    string sTime = request.Inputs["Time"].AsString();
                    string[] sTimes = sTime.Split(':');
                    if (sTimes.Length == 2)
                    {
                        hour = int.Parse(sTimes[0]);
                        minute = int.Parse(sTimes[1]);
                    }
                    if (sTimes.Length == 3)
                    {
                        second = int.Parse(sTimes[2]);
                    }
                }
                DateTime xDate = PatchDay();
                pDay = new DateTime(xDate.Year, xDate.Month, xDate.Day, hour, minute, second);
            }

            if (request.Inputs.Contains("Occurence") & request.Inputs.Contains("Weekday"))
            {
                DateTime dTarget =  TargetDate(pDay, request.Inputs["Occurence"].AsString(), request.Inputs["Weekday"].AsString());
                response.Publish("Date_Target", dTarget);
                
                //Check if target is today..
                if (DateTime.Compare(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day), new DateTime(dTarget.Year, dTarget.Month, dTarget.Day)) == 0)
                {
                    response.Publish("Date_isTargetToday", true);
                }
                else
                {
                    //Check if it's in the past
                    if (DateTime.Compare(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day), new DateTime(dTarget.Year, dTarget.Month, dTarget.Day)) > 0)
                    {
                        response.Publish("Date_isPast", true);
                        response.Publish("Date_TargetNext", TargetDate(PatchDay(pDay.Year, pDay.Month + 1, pDay.Hour, pDay.Minute, pDay.Second), request.Inputs["Occurence"].AsString(), request.Inputs["Weekday"].AsString()));

                    }
                    else
                    {
                        response.Publish("Date_TargetNext", dTarget);
                    }
                }
            }

            response.Publish("Date_Patchday", pDay);
            if (DateTime.Compare(new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day), new DateTime(pDay.Year, pDay.Month, pDay.Day)) > 0)
            {
                response.Publish("Date_PatchdayNext", PatchDay(pDay.Year, pDay.Month + 1, pDay.Hour, pDay.Minute, pDay.Second));
            }
            else
            {
                response.Publish("Date_PatchdayNext", pDay);
            }
            
        }

        /// <summary>
        /// Get PatchDate (2nd Tuesday)
        /// </summary>
        /// <returns>Date of 2nd Tuesday</returns>
        static public DateTime PatchDay()
        {
            return PatchDay(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
        }

        /// <summary>
        /// Get PatchDate (2nd Tuesday)
        /// </summary>
        /// <param name="year"></param>
        /// <param name="month"></param>
        /// <returns>Date of 2nd Tuesday</returns>
        static public DateTime PatchDay(int year, int month, int hour, int minute, int second)
        {
            DateTime firstDay = new DateTime(year, month, 1, hour, minute, second);

            for (int i = 0; i <= 6; i++)
            {

                if (firstDay.DayOfWeek == DayOfWeek.Tuesday)
                {
                    //We want the 2nd Tuesday
                    return firstDay.AddDays(7);
                }

                firstDay = firstDay.AddDays(1);
            }


            return new DateTime();
        }

        /// <summary>
        /// Calculate dates after second tuesday (Patch Day)
        /// </summary>
        /// <param name="PatchDay"></param>
        /// <param name="Occurence">first, secodn, third or fourth</param>
        /// <param name="Weekday">string of System.DayOfWeek</param>
        /// <returns></returns>
        static public DateTime TargetDate(DateTime PatchDay, string Occurence, string Weekday)
        {
            DayOfWeek dOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), Weekday);

            bool found = false;
            DateTime pDay = PatchDay;
            int iOcc = 1;

            switch (Occurence.ToLower().Trim())
            {
                case "first":
                    iOcc = 1;
                    break;
                case "second":
                    iOcc = 2;
                    break;
                case "third":
                    iOcc = 3;
                    break;
                case "fourth":
                    iOcc = 4;
                    break;
                case "fith":
                    iOcc = 5;
                    break;
                case "sixth":
                    iOcc = 6;
                    break;
                case "seventh":
                    iOcc = 7;
                    break;
                case "eighth":
                    iOcc = 8;
                    break;

            }

            while (!found)
            {
                pDay = pDay.AddDays(1);
                if (pDay.DayOfWeek == dOfWeek)
                {
                    found = true;
                    return pDay.AddDays(7 * (iOcc - 1));
                }
            }

            return DateTime.Now;
        }
    }


}
